﻿using System;
using System.IO;
using System.Text;
using System.Runtime.Serialization;
using MSJSON = System.Runtime.Serialization.Json;
using MSFB = System.Runtime.Serialization.Formatters.Binary;
using MSXML = System.Xml.Serialization;
using NSJSON = Newtonsoft.Json;

namespace M
{
	/// <summary>
	/// 友情序列化类
	/// </summary>
	public static class MFormatter
	{
		#region 二进制序列化
		/// <summary>
		/// 将对象通过二进制序列化成字节数组
		/// </summary>
		/// <typeparam name="T">将要序列化的对象的类型</typeparam>
		/// <param name="obj">源对象</param>
		/// <returns>序列化后的字节数组</returns>
		public static byte[] ToBytes<T>(T obj)
		{
			MValidator.CheckForNullReference("Serializing Object", obj);
			using (MemoryStream ms = new MemoryStream())
			{
				MSFB.BinaryFormatter bf = new MSFB.BinaryFormatter();
				bf.Serialize(ms, obj);
				byte[] bs = new byte[ms.Length];
				ms.Read(bs, 0, bs.Length);
				return bs;
			}
		}
		/// <summary>
		/// 通过二进制序列化将字节数组反序列化为对象
		/// </summary>
		/// <typeparam name="T">将要反序列化的对象的类型</typeparam>
		/// <param name="bytes">源字节数组</param>
		/// <returns>反序列化后得到的对象</returns>
		public static T FromBytes<T>(byte[] bytes)
		{
			MValidator.CheckForNullReference("DeSerializing Bytes", bytes);
			using (MemoryStream ms = new MemoryStream())
			{
				ms.Write(bytes, 0, bytes.Length);
				ms.Seek(0, SeekOrigin.Begin);
				return FromStream<T>(ms);
			}
		}
		/// <summary>
		/// 通过二进制序列化将字节流反序列化为对象
		/// </summary>
		/// <typeparam name="T">将要反序列化的对象的类型</typeparam>
		/// <param name="stream">源字节流</param>
		/// <returns>反序列化后得到的对象</returns>
		public static T FromStream<T>(System.IO.Stream stream)
		{
			MValidator.CheckForNullReference("DeSerializing Stream", stream);
			MSFB.BinaryFormatter bf = new MSFB.BinaryFormatter();
			return (T)bf.Deserialize(stream);
		}
		#endregion

		#region XML序列化
		/// <summary>
		/// 将对象通过Xml序列化成Xml字符串（UTF8编码）
		/// </summary>
		/// <typeparam name="T">将要序列化的对象的类型</typeparam>
		/// <param name="obj">源对象</param>
		/// <returns>序列化后的Xml字符串</returns>
		public static string ToXml<T>(T obj)
		{
			return ToXml<T>(obj, Encoding.UTF8);
		}
		/// <summary>
		/// 将对象通过Xml序列化成Xml字符串
		/// </summary>
		/// <typeparam name="T">将要序列化的对象的类型</typeparam>
		/// <param name="obj">源对象</param>
		/// <param name="encoding">序列化目标Xml字符串编码</param>
		/// <returns>序列化后的Xml字符串</returns>
		public static string ToXml<T>(T obj, Encoding encoding)
		{
			MValidator.CheckForNullReference("Serializing Object", obj);
			encoding = encoding ?? System.Text.Encoding.UTF8;
			using (MemoryStream ms = new MemoryStream())
			{
				MSXML.XmlSerializer xs = new MSXML.XmlSerializer(typeof(T));
				xs.Serialize(ms, obj);
				return encoding.GetString(ms.ToArray());
			}
		}
		/// <summary>
		/// 通过Xml序列化将Xml字符串（UTF8编码）反序列化为对象
		/// </summary>
		/// <typeparam name="T">将要反序列化的对象的类型</typeparam>
		/// <param name="xml">源Xml字符串</param>
		/// <returns>反序列化后得到的对象</returns>
		public static T FromXml<T>(string xml)
		{
			return FromXml<T>(xml, Encoding.UTF8);
		}
		/// <summary>
		/// 通过Xml序列化将Xml字符串反序列化为对象
		/// </summary>
		/// <typeparam name="T">将要反序列化的对象的类型</typeparam>
		/// <param name="xml">源Xml字符串</param>
		/// <param name="encoding">源Xml字符串的编码</param>
		/// <returns>反序列化后得到的对象</returns>
		public static T FromXml<T>(string xml, Encoding encoding)
		{
			MValidator.CheckForEmptyString("Xml string", xml);
			encoding = encoding ?? System.Text.Encoding.UTF8;
			using (MemoryStream ms = new MemoryStream(encoding.GetBytes(xml)))
			{
				MSXML.XmlSerializer xs = new MSXML.XmlSerializer(typeof(T));
				return (T)xs.Deserialize(ms);
			}
		}
		#endregion

		#region JSON序列化
		/// <summary>
		/// 将对象通过Json序列化成Json字符串
		/// </summary>
		/// <typeparam name="T">将要序列化的对象的类型</typeparam>
		/// <param name="obj">源对象</param>
		/// <returns>序列化后的Json字符串</returns>
		public static string ToJson<T>(T obj)
		{
			MValidator.CheckForNullReference("Serialize Object", obj);
			NSJSON.JsonSerializerSettings settings = new NSJSON.JsonSerializerSettings();
			settings.ReferenceLoopHandling = NSJSON.ReferenceLoopHandling.Ignore;
			return NSJSON.JsonConvert.SerializeObject(obj, settings);
		}

		/// <summary>
		/// 通过Json序列化将Json字符串反序列化为对象
		/// </summary>
		/// <typeparam name="T">将要反序列化的对象的类型</typeparam>
		/// <param name="jsonString">源Json字符串</param>
		/// <returns>反序列化后得到的对象</returns>
		public static T FromJson<T>(string jsonString)
		{
			MValidator.CheckForEmptyString("Deserialize String", jsonString);
			return NSJSON.JsonConvert.DeserializeObject<T>(jsonString);
		}
		#endregion

		#region 微软的DataContractJSON序列化

		/// <summary>
		/// 将对象通过Json序列化成Json字符串（DataContractJson）
		/// </summary>
		/// <typeparam name="T">将要序列化的对象的类型</typeparam>
		/// <param name="obj">源对象</param>
		/// <returns>序列化后的Json字符串</returns>
		public static string ToDCJson<T>(T obj)
		{
			MValidator.CheckForNullReference("Serialize Object", obj);
			using (MemoryStream ms = new MemoryStream())
			{
				MSJSON.DataContractJsonSerializer jf = new MSJSON.DataContractJsonSerializer(typeof(T));
				jf.WriteObject(ms, obj);
				return Encoding.UTF8.GetString(ms.ToArray());
			}
		}
		/// <summary>
		///  通过Json序列化将Json字符串反序列化为对象（DataContractJson）
		/// </summary>
		/// <typeparam name="T">将要反序列化的对象的类型</typeparam>
		/// <param name="jsonString">源Json字符串</param>
		/// <returns>反序列化后得到的对象</returns>
		public static T FromDCJson<T>(string jsonString)
		{
			MValidator.CheckForEmptyString("Deserialize String", jsonString);
			using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
			{
				MSJSON.DataContractJsonSerializer jf = new MSJSON.DataContractJsonSerializer(typeof(T));
				return (T)Convert.ChangeType(jf.ReadObject(ms), typeof(T));
			}
		}

		#endregion
	}
}
